package net.csdn.business.discuss.common.config;

import com.alibaba.ttl.threadpool.TtlExecutors;
import lombok.Data;
import net.csdn.business.discuss.common.domain.ContextDecorator;
import net.csdn.business.discuss.common.wrapper.ThreadPoolWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author likun
 * @date 2022/6/18 16:11
 */
@Data
@EnableAsync
@Configuration
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "async.thread.pool")
public class AsyncThreadPoolConfig {

    public final static String ASYNC_EXECUTOR_POOL_NAME = "asyncTaskExecutor";

    /**
     * 核心线程数（默认线程数）
     */
    private int coreSize = 20;

    /**
     * 最大线程数
     */
    private int maxSize = 50;

    /**
     * 允许线程空闲时间（单位：默认为秒）
     */
    private int keepAlive = 60;

    /**
     * 缓冲队列数
     */
    private int queueCapacity = 1000;

    /**
     * 线程池名前缀
     */
    private String threadNamePrefix = "async-";

    private long timeOut = 1000L;

    /**
     * 如下方式会使@Async失效
     * 一、异步方法使用static修饰
     * 二、异步类没有使用@Component注解（或其他注解）导致spring无法扫描到异步类
     * 三、异步方法不能与异步方法在同一个类中
     * 四、类中需要使用@Autowired或@Resource等注解自动注入，不能自己手动new对象
     * 五、如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
     * 六、在本类中调用本累得异步方法无效
     *
     * @return ThreadPoolTaskExecutor
     */
    @Bean(ASYNC_EXECUTOR_POOL_NAME)
    //@ConditionalOnMissingBean(ThreadPoolTaskExecutor.class)
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolWrapper.CustomThreadPoolTaskExecutor();
        executor.setCorePoolSize(coreSize);
        executor.setMaxPoolSize(maxSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAlive);
        executor.setThreadNamePrefix(threadNamePrefix);
        //增加多线程中传递父线程信息
        executor.setTaskDecorator(new ContextDecorator());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 线程池对拒绝任务的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        // 默认初始化所有核心线程
        executor.getThreadPoolExecutor().prestartAllCoreThreads();
        return executor;
    }

}